package com.hp.snap.gr.action.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
import org.apache.commons.lang.StringUtils;
import org.codehaus.jettison.json.JSONArray;
import org.codehaus.jettison.json.JSONException;
import org.codehaus.jettison.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.hp.snap.gr.exception.ActionException;
import com.hp.snap.gr.exception.RESTfulException;
import com.hp.snap.gr.model.HostInfo;
import com.hp.snap.gr.model.ServerInfo;
import com.hp.snap.gr.model.jaxb.ActionType;
import com.hp.snap.gr.model.jaxb.GeneralActionType;
import com.hp.snap.gr.model.jaxb.ParameterType;
import com.hp.snap.gr.utils.Constants;
import com.hp.snap.gr.utils.RESTfulUtils;
import com.hp.snap.gr.utils.Utils;

/**
 * Get SessionServers by restful interface.
 * Action output: SessionServers: put the session servers object into output.
 **/
public class GetSessionServerListActionHandler extends AbstractActionHandler {

    private static Logger logger = LoggerFactory.getLogger(GetSessionServerListActionHandler.class);
    private static Pattern URL_PATTERN = Pattern.compile("http://([^/:]+):?(\\d+)?(.*)");

    @Override
    public void execute(ActionType action,
            Map<String, Object> actionPlanInputs,
            Map<String, Object> actionPlanOutputs) throws ActionException {

        GeneralActionType actionType = (GeneralActionType) action;
        List<ParameterType> parameterTypes = actionType.getParameter();
        Map<String, String> parameterMap = Utils.contructParamMap(parameterTypes);
        String excludes = parameterMap.get("excludes");
        Map<String, String> config = (Map<String, String>) actionPlanOutputs.get(Constants.GET_SESSIONSERVER_CONFIG);
        //        String port = parameterMap.get("port");

        String result = null;
        String content = "{  \"subSystem\": \"\","
                + "    \"connector\": \"SSH\"},head:{\"_sman_user\":" +
                config.get(Constants.GET_SESSIONSERVER_CONFIG_USER)
                + ",\"_sman_password\":" + config.get(Constants.GET_SESSIONSERVER_CONFIG_PASSWORD)
                + "}";
        try {
            result = RESTfulUtils
                    .getRESTfulInvokeResultByUrl(config.get(Constants.GET_SESSIONSERVER_CONFIG_URL1), content);
        } catch (RESTfulException e) {
            if (e.getStatusCode() >= 400) {
                if (null != config.get(Constants.GET_SESSIONSERVER_CONFIG_URL2) && !"".equals(config
                        .get(Constants.GET_SESSIONSERVER_CONFIG_URL2))) {
                    result = RESTfulUtils
                            .getRESTfulInvokeResultByUrl(config.get(Constants.GET_SESSIONSERVER_CONFIG_URL2), content);
                }
            }
        }

        List<ServerInfo> res;
        Map<String, List<ServerInfo>> sessionServerMap = new HashMap<>();
        List<ServerInfo> serverInfos = new ArrayList<ServerInfo>();
        List<HostInfo> hostInfos = new ArrayList<HostInfo>();
        try {
            JSONObject object = new JSONObject(result);
            String resultCode = object.getString("resultCode");
            if ("2001".equals(resultCode)) {
                Object o = object.get("apResult");
                JSONArray list = (JSONArray) ((JSONObject) o).get("record");
                for (int i = 0; i < list.length(); i++) {
                    JSONObject record = (JSONObject) list.get(i);
                    String connectorInfo = record.getString("connectorInfo");
                    if (!connectorInfo.isEmpty()) {
                        String[] connectors = connectorInfo.split(",");
                        ServerInfo info = new ServerInfo();
                        HostInfo hostInfo = new HostInfo();
                        Map<String, String> serverInfoTemp = new HashMap<String, String>();
                        for (String connector : connectors) {
                            String[] split = connector.split("=");
                            if (split.length == 2) {
                                serverInfoTemp.put(split[0], split[1]);
                            }
                        }
                        String hostName = serverInfoTemp.get("hostName");
                        if (sessionServerMap.containsKey(hostName)) {
                            res = sessionServerMap.get(hostName);
                        } else {
                            res = new ArrayList<>();
                            sessionServerMap.put(hostName, res);
                        }
                        // Set ServerInfo
                        setServerInfo(record, serverInfoTemp, info);
                        // Set HostInfo
                        setHostInfo(hostInfo, serverInfoTemp);
                        if (!StringUtils.isEmpty(excludes) && excludes.contains(record.getString("subSystem"))) {
                            continue;
                        }
                        if (!hostInfos.contains(hostInfo)) {
                            hostInfos.add(hostInfo);
                        }
                        res.add(info);
                        serverInfos.add(info);
                    }
                }
            }
        } catch (JSONException e) {
            logger.error(e.toString());
            throw new ActionException(e.getMessage(), e);
        }

        StringBuilder out = new StringBuilder();
        for (ServerInfo re : serverInfos) {
            out.append(re.getSubSystem()).append("/").append(re.getHostName()).append("/").append(re.getServerName())
                    .append(" ");
        }
//        logger.debug(Constants.SESSION_SERVER_RESPONSE_TEXT + ":{}", serverInfos);
//        logger.debug(Constants.SESSION_SERVER_RESPONSE_HOST + ":{}", hostInfos);
//        logger.debug(Constants.SESSION_SERVER_RESPONSE_TEXT_CATEGORY + ":{}", sessionServerMap);

        // output to shell command
        Constants.CONSOLE.info("SERVERS_OUTPUT:" + out.toString());

        actionPlanOutputs.put(Constants.SESSION_SERVER_RESPONSE_TEXT, serverInfos);
        actionPlanOutputs.put(Constants.SESSION_SERVER_RESPONSE_HOST, hostInfos);
        actionPlanOutputs.put(Constants.SESSION_SERVER_RESPONSE_TEXT_CATEGORY, sessionServerMap);
    }

    /**
     * Set ServerInfo
     *
     * @param record
     * @param serverInfoTemp
     * @param info
     * @throws JSONException
     */
    public void setServerInfo(JSONObject record, Map<String, String> serverInfoTemp, ServerInfo info) throws JSONException {
        info.setHostIp(serverInfoTemp.get("hostIp"));
        info.setHostName(serverInfoTemp.get("hostName"));
        info.setLogin(serverInfoTemp.get("login"));
        info.setSshKey(serverInfoTemp.get("sshKey"));
        info.seteIUMHostId(serverInfoTemp.get("eIUMHostId"));
        info.seteIUMInstance(serverInfoTemp.get("eIUMInstance"));
        info.setRtcHome(serverInfoTemp.get("rtcHome"));

        info.setConnectorName(record.getString("connectorName"));
        info.setServerName(record.getString("serverName"));
        info.setSiteId(record.getString("siteId"));
        info.setSubSystem(record.getString("subSystem"));
    }

    /**
     * Set HostInfo
     *
     * @param hostInfo
     * @param serverInfoTemp
     */
    public void setHostInfo(HostInfo hostInfo, Map<String, String> serverInfoTemp) {
        hostInfo.setHostIp(serverInfoTemp.get("hostIp"));
        hostInfo.setHostName(serverInfoTemp.get("hostName"));
        hostInfo.setLogin(serverInfoTemp.get("login"));
        hostInfo.setSshKey(serverInfoTemp.get("sshKey"));
        hostInfo.seteIUMHostId(serverInfoTemp.get("eIUMHostId"));
        hostInfo.seteIUMInstance(serverInfoTemp.get("eIUMInstance"));
        hostInfo.setRtcHome(serverInfoTemp.get("rtcHome"));
    }
}
